const library = require("../library/index.js");


module.exports = function(lab){

    return {
        @reauth : function(credential, service_info) {

            return @.async(function(){
                
                this.pool.local = library.generateKeyAndID();

                this.pool.local_key = {
                    id          : this.pool.local.id,
                    uid         : credential.id,
                    service_id  : service_info ? service_info.id : null,
                    credential  : credential,
                    local_key   : this.pool.local.public_key,
                    create_date : Date.now(),
                    expire_date : Date.now() + (credential.expire_date || @lab.constants.backend_key_expire_timeout)
                }

                if (service_info) {

                    @info("try to exchange key with : ");
                    @info(service_info.value);
                    this.next({
                        id  : this.pool.local_key.id,
                        key : this.pool.local_key.key, 
                    });

                    // @lab.jsonrpc(service_info.value).call("backend@keys.exchange",this.pool.local_key,function(error,result){

                    //     if (error) {
                    //         this.reject(error);
                    //     } else {
                    //         this.next(result);
                    //     }
    
                    // }.bind(this));

                } else {

                    lab.backend.keys.exchange(null,this.pool.local_key).pipe(this);

                }

            }).then(function(exchange_result){

                this.pool.local_key.remote_key = exchange_result.key;
                this.pool.local_key.remote_id  = exchange_result.id;

                lab.create("backend_service_keyrings", this.pool.local_key).resolve({
                    id        : exchange_result.id,
                    key       : exchange_result.public_key,
                    signature : exchange_result.signature
                }).pipe(this);

            })
        },
        exchange : function(session, key_ring){

            if (!key_ring.id) {
                throw @lab.errors.invalid_parameters;
            }
            if (!key_ring.local_key) {
                throw @lab.errors.invalid_parameters;
            }
            if (!key_ring.credential) {
                throw @lab.errors.invalid_parameters;
            }

            return @.async(function(){

                lab.sqlite.find("backend_service_keyrings",{
                    remote_id  : key_ring.id
                }).then(function(result){

                    if (result.records.length) {
                        throw @lab.errors.dulplicate_key_id;
                    } else {
                        this.next();
                    }

                }).pipe(this);

            }).then(function(){

                var local = library.generateKeyAndID();

                var local_key = {
                    id          : local.id,
                    scene       : key_ring.scene,

                    local_key   : local.public_key,

                    remote_id   : key_ring.id,
                    remote_key  : key_ring.local_key,
                    service_id  : key_ring.service_id,

                    credential  : key_ring.credential,
                    create_date : Date.now(),
                    expire_date : Date.now() + @lab.constants.backend_key_expire_timeout
                };

                lab.create("backend_service_keyrings", local_key).resolve({
                    id          : local.id,
                    key         : local.public_key,
                    signature   : local.signature
                }).pipe(this);

            })
        },
        participant : function (session, form) {
            
            return @.async(function(){
                if (!form) {
                    throw @lab.errors.invalid_parameters;
                }

                if (@.is(form,String)) {

                    if (form.length >= 24){

                        var formBuffer = Buffer.from(form,"base64");    
                        var idBuffer   = formBuffer.slice(0,16).toString("hex");
                        var keyBuffer  = formBuffer.slice(16).toString("base64");

                        this.next({
                            "id"  : idBuffer,
                            "key" : keyBuffer
                        });

                    } else {
                        throw @lab.errors.key_length;
                    }
                } else if (@.is(form,Object)) {

                    if (form.id && form.key) {
                        this.next(form);
                    } else {
                        throw @lab.errors.invalid_parameters;
                    }

                } else {
                    throw @lab.errors.invalid_parameters;
                }
            }).then(function(key_ring){

                this.pool.key_ring = key_ring;

                lab.sqlite.find("backend_service_keyrings",{
                    remote_id : key_ring.id
                }).then(function(keyring_search_result){
                    
                    if (keyring_search_result.records.length && library.verifyKeyAndID(key_ring.id, keyring_search_result.records[0].remote_key,key_ring.key)) {

                        var credential = keyring_search_result.records[0].credential;

                        delete session.currentOU;
                        delete session.currentUser;

                        if (credential.ouid) {
                            session.currentOU = {
                                id   : credential.ouid,
                                name : credential.ou_name
                            };
                        }

                        session.currentUser = {
                            id   : credential.id,
                            name : credential.name,
                            ouid : credential.ouid,
                        }

                        if (keyring_search_result.records[0].expire_date < Date.now()){

                            library.createKeyAndID(lab, session).then(function(result){

                                keyring_search_result.records[0].remote_id   = result.id;
                                keyring_search_result.records[0].remote_key  = result.key;
                                keyring_search_result.records[0].expire_date = Date.now() + @lab.constants.backend_key_expire_timeout;
    
                                lab.update("backend_service_keyrings",keyring_search_result.records[0]).resolve({
                                    id  : result.id,
                                    key : result.signature
                                }).pipe(this);
    
                            }).pipe(this);

                        } else {
                            this.next(key_ring)
                        }

                    } else {
                        throw @lab.errors.invalid_keys;
                    }

                }).pipe(this);

            })
        },
        auth : function(session, service){

            if (!session.currentUser) {
                throw @lab.errors.not_login;
            }

            if (!session.currentOU || !service) {
                throw @lab.errors.service_not_found;
            }

            return @.async(function(){

                lab.sqlite.find("backend_service_settings",{
                    name : service, 
                    ouid : session.currentOU.id
                }).then(function(result){

                    if (result.records.length && result.records[0].value) {
                        this.next(result.records[0]);
                    } else {
                        throw @lab.errors.service_not_found;
                    }

                }).pipe(this);

            }).then(function(service_info){

                lab.sqlite.find("backend_service_keyrings",{

                    service_id  : service_info.id,
                    ouid        : session.currentOU.id,
                    uid         : session.currentUser.id,
                    expire_date : [">" , Date.now()]

                },1,0,["create_date","desc"]).then(function(result){

                    if (result.records.length){
                        this.next(result.records[0]);
                    } else {
                        lab.backend.keys.@reauth({
                            id      : session.currentUser.id,
                            name    : session.currentUser.name,
                            ouid    : session.currentOU.id,
                            ou_name : session.currentOU.name,
                        }, service_info).pipe(this);
                    }

                }).pipe(this);

            })

        }
    }
}